package com.talkyun.openx.ocean.codec;

import com.talkyun.utils.json.JSONObject;
import com.talkyun.utils.para.ParaNamer;

import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;

/**
 * @author kevin
 */
public class MethodFinder {

    private ParaNamer namer = new ParaNamer();

    public Method findBestMatchMethod(Class<?> clazz, String methodName, JSONObject args) {
        List<Method> list = getMethodByName(clazz, methodName);
        if (list.isEmpty()) {
            return null;
        } else if (list.size() == 1) {
            return list.get(0);
        }

        // same name method matcher
        for (Method m : list) {
            boolean match = true;
            List<ParaNamer.Param> kvs = namer.getParaList(m);
            for (ParaNamer.Param p : kvs) {
                if (!args.exists(p.getName())) {
                    match = false;
                    break;
                }
            }

            // include all method's arg-name
            if (match) {
                return m;
            }
        }

        return null;
    }

    private List<Method> getMethodByName(Class<?> clazz, String method) {
        Method[] all = clazz.getMethods();
        List<Method> list = new ArrayList<Method>();
        for (Method m : all) {
            if (method.equalsIgnoreCase(m.getName())) {
                list.add(m);
            }
        }

        Collections.sort(list, new Comparator<Method>() {
            @Override
            public int compare(Method m1, Method m2) {
                if (m1.getParameterTypes().length == m2.getParameterTypes().length) {
                    return 0;
                } else if (m1.getParameterTypes().length > m2.getParameterTypes().length) {
                    return -1;
                } else {
                    return 1;
                }
            }
        });

        return list;
    }
}